import 'package:flutter/material.dart';

class Joystick extends StatefulWidget {
  final ValueChanged<Offset> onDirectionChanged;
  final int maxFrequency; // 最高频率（单位：Hz，即每秒最多触发多少次）
  final double touchAreaWidth; // 可触摸区域的宽度
  final double touchAreaHeight; // 可触摸区域的高度
  final double outerRadius; // 外圈半径
  final double innerRadius; // 内圈半径
  final Color backgroundColor; // 可触摸区域的背景颜色

  const Joystick({
    Key? key,
    required this.onDirectionChanged,
    this.maxFrequency = 10, // 默认每秒最多触发 10 次
    this.touchAreaWidth = 200.0, // 默认可触摸区域宽度为 200
    this.touchAreaHeight = 200.0, // 默认可触摸区域高度为 200
    this.outerRadius = 50.0, // 默认外圈半径为 50
    this.innerRadius = 25.0, // 默认内圈半径为 25
    this.backgroundColor = Colors.white, // 默认背景颜色为透明
  }) : super(key: key);

  @override
  _JoystickState createState() => _JoystickState();
}

class _JoystickState extends State<Joystick> {
  Offset _stickPosition = Offset.zero; // 摇杆手柄的位置
  bool _isDragging = false; // 是否正在拖动
  Offset? _initialPosition; // 摇杆初始中心位置

  // 摇杆手柄的最大移动范围
  double get _maxDragDistance => widget.outerRadius - widget.innerRadius;

  // 用于限制回调频率的变量
  DateTime? _lastCallbackTime;

  void _updatePosition(Offset newPosition) {
    // 计算摇杆手柄到中心的距离
    final double distance = newPosition.distance;

    // 如果距离超出最大范围，限制摇杆手柄的位置
    if (distance > _maxDragDistance) {
      newPosition = newPosition * (_maxDragDistance / distance);
    }

    setState(() {
      _stickPosition = newPosition;
      _isDragging = true;
    });

    // 归一化坐标：将位置除以外圈的有效范围半径
    final Offset normalizedOffset = newPosition / _maxDragDistance;

    // 限制回调频率
    final DateTime now = DateTime.now();
    if (_lastCallbackTime == null ||
        now.difference(_lastCallbackTime!).inMilliseconds >= 1000 ~/ widget.maxFrequency) {
      _lastCallbackTime = now;
      widget.onDirectionChanged(normalizedOffset);
    }
  }

  void _resetPosition() {
    setState(() {
      _stickPosition = Offset.zero;
      _isDragging = false;
      _initialPosition = null; // 重置初始位置
    });

    // 触发回调，传递中心位置（归一化坐标为 Offset.zero）
    widget.onDirectionChanged(Offset.zero);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onPanStart: (details) {
        // 初始化摇杆中心位置
        setState(() {
          _initialPosition = details.localPosition;
        });
        _updatePosition(details.localPosition - _initialPosition!);
      },
      onPanUpdate: (details) {
        if (_initialPosition != null) {
          _updatePosition(details.localPosition - _initialPosition!);
        }
      },
      onPanEnd: (details) {
        _resetPosition();
      },
      onPanCancel: () {
        _resetPosition();
      },
      child: Container(
        width: widget.touchAreaWidth,
        height: widget.touchAreaHeight,
        decoration: BoxDecoration(
          color: widget.backgroundColor, // 设置背景颜色
          border: Border.all(color: Colors.grey, width: 2.0), // 可触摸区域的边框
          borderRadius: BorderRadius.circular(8.0),
        ),
        child: Stack(
          children: [
            if (_initialPosition != null)
              Positioned(
                left: _initialPosition!.dx - widget.outerRadius,
                top: _initialPosition!.dy - widget.outerRadius,
                child: Opacity(
                  opacity: _isDragging ? 1.0 : 0.0, // 只有在拖动时显示摇杆
                  child: Container(
                    width: widget.outerRadius * 2,
                    height: widget.outerRadius * 2,
                    decoration: BoxDecoration(
                      color: Colors.grey[300],
                      shape: BoxShape.circle,
                    ),
                    child: Center(
                      child: Transform.translate(
                        offset: _stickPosition,
                        child: Container(
                          width: widget.innerRadius * 2,
                          height: widget.innerRadius * 2,
                          decoration: BoxDecoration(
                            color: _isDragging ? Colors.blue : Colors.grey,
                            shape: BoxShape.circle,
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }
}